/***************************************************************************\
 * Copyright (C) by Keio University
 * OpenNISensor.hpp created in 02 2013.
 * Mail : fdesorbi@hvrl.ics.keio.ac.jp
 *
 * OpenNISensor.hpp is part of HVRL Engine Library.
 *
 * The HVRL Engine Library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * The HVRL Engine Library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 \***************************************************************************/

#ifndef HVRL_OPENNI_SENSOR_HPP__
#define HVRL_OPENNI_SENSOR_HPP__

#include "hvrl/sensor/OpenNISensorDriver.hpp"
#include "hvrl/sensor/Sensor.hpp"

#include <XnCppWrapper.h>

#include <boost/thread.hpp>

namespace hvrl {

class OpenNISensor: public Sensor {

public:

	/**
	 * \brief Constructor for a kinect device using the OpenNI API.
	 *
	 * \param id the id of the device defined between 0 and the number of devices - 1 obtained through the OpenNI driver
	 * \param driver the corresponding OpenNI driver
	 * \author Francois de Sorbier
	 * \sa OpenNISensorDriver::getNumberOfSensors
	 */
	OpenNISensor(const unsigned int& id,
			const hvrl::OpenNISensorDriver& driver);

	/**
	 * \brief Destructor.
	 *
	 * \author Francois de Sorbier
	 */
	~OpenNISensor(void);

	/**
	 * \brief Return the name of the the OpenNI device.
	 *
	 * \author Francois de Sorbier
	 * return the name of the device
	 */
	std::string getName(void) const {
		return this->devicename;
	}

	/**
	 * \brief Return the images captured by the sensor.
	 *
	 * The images are a depth map and a color image
	 *
	 * \author Francois de Sorbier
	 */
	RGBDImage* getImage(void) {
		boost::mutex::scoped_lock l(mutex);
		return &rgbd;
	}

	unsigned char * getColorData(void);

	short unsigned int * getDepthData(void);

	bool getValuef(const std::string& name, float& value);

	unsigned int getID(void) const {
		return this->device_id;
	}

	bool isRunning(void) const {
		return this->running;
	}

	PointCloud* getPointCloud(void);

	virtual Size getResolution(void) const{
		return Size(outputMode.nXRes,outputMode.nYRes);
	}

public:

	void pause(void);

	void play(void);

	void stop(void);

	boost::signals2::signal<void ()>& getUpdatedSignal(void){
		return this->signal_updated;
	}

	boost::signals2::signal<void ()>& getReadySignal(void){
		return this->signal_ready;
	}

protected:

	void updated(void);

	void ready(void);

private:
	void run(void);

private:
	xn::Device device;
	xn::DepthGenerator depth;
	xn::IRGenerator ir;
	xn::ImageGenerator color;
	xn::DepthMetaData depthmetadata;
	xn::ImageMetaData colormetadata;
	xn::IRMetaData irmetadata;
	XnMapOutputMode outputMode;

	xn::Context context;

	std::string devicename;
	unsigned int device_id;

	bool paused;
	bool grabcolor;
	bool running;
	bool finished;
	bool updatepc;

	float bpcoeff;

	RGBDImage rgbd;

	PointCloud pc;

	boost::signals2::signal<void ()> signal_updated;
	boost::signals2::signal<void ()> signal_ready;
	boost::thread *pthread;

	boost::mutex mutex;


};

}

#endif
